<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

</body>
<script>
  /*
    观察者模式
        例子：监控
          我们坐在教室里面就是  被观察者
          监控后面的老师，就是  观察者
          当被观察者触发了一些条件的时候，观察者就会触发技能
        观察者模式：监控一个 对象 的状态，一旦状态发生改变，马上触发技能
          需要两个构造函数来实现
          1、创建被观察者
            属性，自己的状态
            队列，记录都有谁观察着自己，数组[]
            方法，能设置自己的状态，当我需要改变的时候，要触发这个方法改变状态
            方法，添加观察者
            方法，删除观察者
          2、创建观察者
            需要一个身份证明
            需要一个技能
  */

  // 观察者构造函数
  class Observer {
    constructor(name, fn = () => { }) {
      this.name = name;
      this.fn = fn;
    }
  }

  // 创建两个观察者
  const bzr = new Observer('班主任', (state) => { console.log('因为:' + state + '，把你家长叫来') })
  const njzr = new Observer('年纪主任', (state) => { console.log('因为:' + state + '，问你你是那个班的？') })
  const xz = new Observer('校长', (state) => { console.log('因为:' + state + '，骂你的班主任') })

  console.log(bzr, xz)

  // 被观察者的构造函数
  class Subject {
    constructor(state) {
      this.state = state;
      // 数组用来保存观察着我的人
      this.observers = [];
    }

    // 设置自己的状态
    setState(val) {
      this.state = val;
      // 就需要把 我的所有观察者的技能都触发
      // 遍历 this.observers 一次触发技能
      this.observers.forEach(item => {
        // item 就是每一个观察者，就是一个一个的对象
        // console.log(item)
        // 告诉他我改变成了什么状态
        item.fn(this.state)
      })
    }

    // 添加观察者
    addObserver(obs) {
      // 谁是观察者，就传递谁进来
      // 判断一下，如果观察者已存在，就不添加了
      // some()
      // const res = this.observers.some(item => item === obs)
      // find()
      // const res = this.observers.find(item => item === obs)
      // indexOf()
      // const res = this.observers.indexOf(obs)
      // filter()
      // const res = this.observers.filter(item => item === obs)
      this.observers = this.observers.filter(item => item !== obs)
      // findIndex()
      // const res = this.observers.findIndex(item => item === obs)
      this.observers.push(obs);
    }

    // 删除观察者
    delObserver(obs) {
      // 把 obs 观察者删除
      // 直接使用 filter 方法
      this.observers.filter(item => item !== obs)
    }
  }

  // 创建一个被观察者
  const xiaoming = new Subject('学习');

  // 给 xiaoming 添加一个观察者
  xiaoming.addObserver(njzr);
  xiaoming.addObserver(bzr);
  xiaoming.addObserver(xz);

  console.log(xiaoming);

  // 创建一个被观察者
  const xiaohong = new Subject('学习');

  // 给 xiaoming 添加一个观察者
  xiaoming.addObserver(bzr);
  xiaoming.addObserver(xz);





</script>

</html>